package com.just.fun.arithmetic;

import java.util.concurrent.TimeUnit;

/**
 * 滑动窗口限流
 */
public class SlidingWindow {

    /**
     * 单位时间内分成多少块
     */
    private int slot;

    /**
     * 单位时间内的次数
     */
    private long limit;
//    /**
//     * 单位时间
//     */
//    private TimeUnit timeUnit;
    /**
     * 记录滑动窗口的链表
     */
    private SlidingNode lastNode;
    /**
     * 每个slot的时间段
     */
    private long slotTime;

    //单位时间为1000，单位ms
    private long unitTime=1000;

    private void init(){
        SlidingNode currentNode=null;
        long current=System.currentTimeMillis();
        for (int i = 0; i < slot; i++) {
            if(lastNode==null){
               lastNode=new SlidingNode(i+1,current,0);
               currentNode=lastNode;
            }else{
                lastNode.setNext(new SlidingNode(i+1,current,0));
                lastNode=lastNode.getNext();
            }
        }
        lastNode.setNext(currentNode);
        slotTime=1000/slot;
    }

    SlidingWindow(int slot,long limit){
       this.slot=slot;
       this.limit=limit;
       init();
    }

    private void reset(int num,long currentMills){
        if(num==0){
            return;
        }
        SlidingNode currentNode=lastNode;
        for (int i = 0; i < num; i++) {
            currentNode=currentNode.getNext();
        }
        currentNode.setTime(currentMills);
        currentNode.setCounter(0);
        lastNode=currentNode;
    }

    public void reset(){
        long currentMills=System.currentTimeMillis();
        long time=lastNode.getTime();
        int count=(int)((currentMills-time)/slotTime);
        if(count>slot){
            reset(count,currentMills);
        }
    }

    private long getSum(){
        SlidingNode currentNode=lastNode;
        long sum=0;
        for (int i = 0; i < slot; i++) {
            sum+=currentNode.getCounter();
            currentNode=currentNode.getNext();
        }
        return sum;
    }

    public synchronized boolean checkAndAdd(){
        reset();
        long sum=getSum();
        System.out.println(sum);
        if(sum>=limit){
            return false;
        }
        lastNode.addCounter();
        return true;
     }

}
